Skip to content

Bound DDS cubemap counts before face-count conversion - #745

Merged
Chuck Walbourn (walbourn) merged 2 commits into
microsoft:mainfrom
ShumWengSang:fix/dds-cubemap-face-count
Sep 29, 2026
Merged

Chuck Walbourn (walbourn) merged 2 commits into
microsoft:mainfrom
ShumWengSang:fix/dds-cubemap-face-count

Conversation

@ShumWengSang

@ShumWengSang Roland Shum (ShumWengSang) commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Bound the DX10 cubemap count to UINT16_MAX before multiplying it by six to obtain the face count. Counts above that limit return HRESULT_E_ARITHMETIC_OVERFLOW.

This follows the review clarification to bound the input cubemap count, not the resulting face count. The check remains after zero-count normalization and applies on both 32-bit and 64-bit targets, including when DDS_FLAGS_ALLOW_LARGE_FILES is enabled. This deliberately replaces the earlier machine-width-dependent representability check with a stricter, architecture-independent input limit.

The existing final hardware-limit checks remain unchanged: without the large-file option, the face count is still limited to 2048. With that option, an input count of 65535 remains acceptable to metadata parsing and yields 393210 faces; 65536 is rejected before multiplication. The accepted large boundary was tested through metadata parsing only, not image loading.

Validation

  • Native x86 and x64 Release library builds passed.
  • A focused local harness passed 23 named checks on each architecture: 11 ordinary/boundary checks and 12 fixture/API checks.
  • Boundary checks cover zero/one-cube behavior, the existing 341/342-cube hardware boundary, and the new 65535/65536-cube boundary with default and large-file flags. Complete image loading is used only for the ordinary one-cube cases.
  • The exact companion fixture returns arithmetic overflow from memory/file metadata and load APIs under default, large-file, and fuzz-stage flag combinations. The candidate load checks leave the image empty.
  • Runs used a 256 MiB process-tree limit and a 90-second timeout. Library hashes were recorded before linking the harness, executable hashes before execution, and both were checked unchanged afterward.
  • The repository's CI clang-format configuration and git diff --check pass.

Companion and limits

The maintained corpus fixture is proposed in walbourn/directxtextest#77. That PR replaces its earlier C++ helper with one small DDS file; this source PR contains no test-suite files.

The focused harness is local validation, not a full maintained-suite pass. Full-suite validation remains pending because the configured media corpus is unavailable locally. Historical validation of the earlier representability-only revision is not being presented as validation of this new policy. This is a correctness change, not a memory-safety or exploitability claim.

Comment thread DirectXTex/DirectXTexDDS.cpp Outdated
if (d3d10ext->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE)
{
// DDS_HEADER_DXT10.arraySize is a count of cubemaps; TexMetadata stores their faces.
if (metadata.arraySize > (SIZE_MAX / 6))

@walbourn Chuck Walbourn (walbourn) Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can safely make this bound:

if (metadata.arraySize > UINT16_MAX)
{
    return HRESULT_E_ARITHMETIC_OVERFLOW;
}

Direct3D Hardware maximums are below this, and Direct3D12 actually uses a 16-bit uint for the DepthOrArraySize field.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to use UINT16_MAX. Just confirming: do you intend that bound on the input cubemap count before multiplying by six, or on the resulting face count?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bounding it before the multiply solves the overflow problem. There's already a check below (applied unless using "ALLOW_LARGE_FILES") which will bound the final value to the actual hardware limits of Direct3D (which is 2048)

@walbourn Chuck Walbourn (walbourn) added bug dds DirectDraw Surface (DDS) labels Sep 25, 2026
@ShumWengSang Roland Shum (ShumWengSang) changed the title Validate DX10 cubemap face-count conversion on 32-bit builds Bound DDS cubemap counts before face-count conversion Sep 29, 2026
@ShumWengSang
Roland Shum (ShumWengSang) marked this pull request as ready for review September 29, 2026 19:13
@walbourn
Chuck Walbourn (walbourn) merged commit 4c5123d into microsoft:main Sep 29, 2026
113 of 119 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug dds DirectDraw Surface (DDS)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants